package com.cy.jt.system.service.aspect;

import com.cy.common.annotation.RequiredLog;
import com.cy.jt.common.domain.SysLog;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
@Aspect
@Component
public class SysLogAspect {
    @Pointcut("@annotation(com.cy.common.annotation.RequiredLog)")
    public void doLog(){}
    @Around("doLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature =(MethodSignature) joinPoint.getSignature();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        String s = className + "." + methodName;
        long l = System.currentTimeMillis();
        log.debug("around.defor {}",l);
        try {
            Object result = joinPoint.proceed();
            long l1 = System.currentTimeMillis();
            log.debug("around.after {}", l1);
            System.out.println(s+"----time="+(l1-l));
            return result;
        }catch (Exception e){
            log.error("execption {}",e.getMessage());
        }
        return null;
    }
    /*
        获取用户的详细操作日志:谁(ip+username)在什么时间点执行了什么操作,
        访问了哪个方法,传递了什么参数.耗时多长.
        */
    private void doLogInfo(ProceedingJoinPoint joinPoint,
                           long time,
                           Throwable e) throws JsonProcessingException, NoSuchMethodException {
        //1.获取用户操作日志
        //1.1获取ip地址(暂时没有时,先用假数据替换)
        String ip="192.168.126.128";
        //1.2获取登录用户名(暂时没有时,先用假数据替换)
        String username="tony";
        //1.3获取具体操作(定义在了RequiredLog注解中)
        //1.3.1获取目标类型(代理对象的目标)
        Class<?> targetCls=joinPoint.getTarget().getClass();
        //1.3.2获取目标方法(类,方法名,参数列表)
        MethodSignature methodSignature=
                (MethodSignature) joinPoint.getSignature();
        //Method targetMethod=methodSignature.getMethod();//假如目标类实现了接口,则这种方式默认获取接口中的方法
        String methodName=methodSignature.getName();
        Method targetMethod=targetCls.getMethod(methodName,
                methodSignature.getParameterTypes());
        //1.3.3获取方法上的RequiredLog注解
        RequiredLog requiredLog=targetMethod.getAnnotation(RequiredLog.class);
        //1.3.4获取方法上的操作名
        String operation=requiredLog.operation();
        //1.4获取方法声明信息
        String targetClassMethodName=targetCls.getClass().getName()+"."+methodName;//类全名.方法
        //1.5获取方法执行时的实际参数,并将其转换为json字符串
        String params=new ObjectMapper().writeValueAsString(joinPoint.getArgs());
        //2.封装操作日志(pojo对象)
        SysLog sysLog=new SysLog();
        sysLog.setIp(ip);
        sysLog.setUsername(username);
        sysLog.setCreatedTime(new Date());
        sysLog.setOperation(operation);
        sysLog.setMethod(targetClassMethodName);
        sysLog.setParams(params);
        if(e!=null) {
            sysLog.setError(e.getMessage());
            sysLog.setStatus(0);
        }
        sysLog.setTime(time);
        //3.输出或记录操作日志
        String logJsonStr=
                new ObjectMapper().writeValueAsString(sysLog);
        log.info("log info {}",logJsonStr);
        //后续将日志写入到数据库
    }

}
